﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PServiceBus.Core.Interface;
using System.Runtime.Serialization;
using System.ComponentModel.Composition;
using PServiceBus.Core.Runtime.Transports;
using System.Net.Mail;
using System.IO;
using PServiceBus.Core.Runtime;
using System.Net;
using PServiceBus.Core.Runtime.Messages;
using System.Text.RegularExpressions;
using PServiceBus.Core.Runtime.Extensions;

namespace PServiceBus.EmailTransport {
    [Serializable]
    [DataContract]
    [Export(typeof(ITransport))]
    public class EmailTransport : ITransport {

        static EmailTransport() {
            SerializationBootstrapper.Configure();
        }

        [DataMember]
        public string From { get; set; }
        [DataMember]
        public string To { get; set; }
        [DataMember]
        public string Subject { get; set; }
        [DataMember]
        public string Host { get; set; }
        [DataMember]
        public string UserName { get; set; }
        [DataMember]
        public string Password { get; set; }
        [DataMember]
        public string ReplyTo { get; set; }
        [DataMember]
        public int Port { get; set; }
        [DataMember]
        public bool IsSSL { get; set; }
        [DataMember]
        public bool SendMessageAsAttachment { get; set; }
        [DataMember]
        public string AttachmentFileName { get; set; }
        [DataMember]
        public string BodyTemplate { get; set; }

        #region ITransport Members
        [DataMember]
        public TransportFormat Format { get; set; }

        [MessageShark.MessageSharkIgnore]
        private MessageMapper _messageMapper;

        public TransportResponse Send(string message, Dictionary<string, object> messageStructure) {
            var tranResponse = TransportResponse.New<EmailTransport>();
            try {
                _messageMapper = MessageMapper.Map(message, messageStructure);
                foreach (var msg in _messageMapper.Tokens) SendEmail(TransformTemplate(msg));
                tranResponse.Success = true;
            }
            catch (Exception ex) {
                tranResponse.Message = ex.ToString();
            }
            return tranResponse;
        }

        public void SendEmail(string message) {
            var msg = new MailMessage(From, To);
            var ms = default(MemoryStream);
            msg.IsBodyHtml = true;
            msg.Subject = Subject ?? string.Empty;
            msg.Body = String.Format("{0}", SendMessageAsAttachment ? string.Empty : message);
            if (SendMessageAsAttachment) {
                ms = new MemoryStream(Encoding.UTF8.GetBytes(message));
                msg.Attachments.Add(new Attachment(ms, AttachmentFileName ?? "PServiceBus.ESBMessage"));
            }
            if (!String.IsNullOrWhiteSpace(ReplyTo)) msg.ReplyToList.Add(new MailAddress(ReplyTo));
            var client = new SmtpClient(Host, Port);
            client.EnableSsl = IsSSL;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            if (!String.IsNullOrWhiteSpace(UserName) && !String.IsNullOrWhiteSpace(Password)) {
                client.UseDefaultCredentials = false;
                client.Credentials = new NetworkCredential(UserName, Password);
            }
            client.Send(msg);
            if (ms != null) MethodHelper.Try(() => ms.Dispose());
        }

        public string TransformTemplate(MessageMapperToken message) {
            return message.TransformTemplate(BodyTemplate);
        }
        #endregion
    }
}
